package com.rm.zeyou.util.task;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

@EnableAsync
@Configuration
public class ScheduledConfig {
    // 获取处理器数量
    private final int cpuNum = Runtime.getRuntime().availableProcessors();
    /**
     * 核心线程数
     */
    private final int corePoolSize = cpuNum * 2;
    /**
     * 最大线程数
     */
    // 根据cpu数量,计算出合理的线程并发数
    private final int maxPoolSize = cpuNum * 2 + 1;
    /**
     * 任务队列容量（阻塞队列）
     */
    private int queueCapacity = 60;
    /**
     * 线程空闲时间
     */
    private int keepAliveTime = 60 * 1000;

    @Bean(name = "taskExecutor")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //设置核心线程数
        executor.setCorePoolSize(corePoolSize);
        //设置最大线程数
        executor.setMaxPoolSize(maxPoolSize);
        //设置任务队列容量
        executor.setQueueCapacity(queueCapacity);
        //设置线程活跃时间（秒）
        executor.setKeepAliveSeconds(keepAliveTime);
        //设置默认线程名称(线程前缀名称，有助于区分不同线程池之间的线程比如：taskExecutor-query-)
        executor.setThreadNamePrefix("taskExecutor-");
        //设置拒绝策略
        // rejection-policy：当pool已经达到max size的时候，如何处理新任务
        //     1、CallerRunsPolicy：不在新线程中执行任务，而是由调用者所在的线程来执行。
        //        "该策略既不会抛弃任务，也不会抛出异常，而是将任务回推到调用者。"顾名思义，在饱和的情况下，调用者会执行该任务（而不是由多线程执行）
        //     2、AbortPolicy：拒绝策略，直接拒绝抛出异常
        //     3、。。。
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //设置允许核心线程超时，默认是false
        executor.setAllowCoreThreadTimeOut(false);
        return executor;
    }

}
